// seg_driver模块定义开始，用于驱动七段显示器
module seg_driver(
    input wire Clk,        // 时钟信号输入
    input wire Rst_n,      // 复位信号输入，低电平有效

    input wire [18:0] data_o, // 输入的数字数据，即测得的距离数据

    //第1个七段显示器的段选信号输出
    output  wire [6:0]  hex1    ,
    output  wire [6:0]  hex2    ,
    output  wire [6:0]  hex3    ,
    output  wire [6:0]  hex4    ,
    output  wire [6:0]  hex5    ,
    output  wire [6:0]  hex6    ,
    output  wire [6:0]  hex7    ,
    output  wire [6:0]  hex8     
);


/*
通过cnt_20us计数器实现动态扫描定时，sel_r选择寄存器用于选择当前激活的七段显示器。
根据sel_r的选择，从data_o中提取相应的数字，并将其转换为七段显示器的段选编码seg_r。
最后，根据sel_r的选择，将seg_r的值赋给对应的七段显示器输出寄存器，并从这些寄存器输出到实际的七段显示器硬件上。
NOTION和FUSHU参数分别定义了消隐和小数点的编码，用于控制七段显示器的显示。
*/

// 参数定义
parameter   NOTION  = 4'd10,// 定义数字"10"用于消隐的编码
            FUSHU   = 4'd11;

parameter   MAX20us = 10'd1000;// 定义20微秒计数器的最大值

reg [9:0]   cnt_20us        ;  // 20微秒计数器
reg [7:0]   sel_r           ;  // 选择寄存器，用于动态扫描控制 片选信号
reg [3:0]   number          ;  // 要显示的数字 0-9
reg [6:0]   seg_r           ;  // 七段显示器的段选编码 段选信号

// 第n个七段显示器的段选编码寄存器
reg [6:0]   hex1_r          ;
reg [6:0]   hex2_r          ;
reg [6:0]   hex3_r          ;
reg [6:0]   hex4_r          ;
reg [6:0]   hex5_r          ;
reg [6:0]   hex6_r          ;
reg [6:0]   hex7_r          ;
reg [6:0]   hex8_r          ;



// 20微秒计数器逻辑，用于动态扫描定时
always @(posedge Clk or negedge Rst_n) begin
    if (!Rst_n) begin
        cnt_20us <= 10'd0;
    end
    else if (cnt_20us == MAX20us - 1'd1) begin
        cnt_20us <= 10'd0;
    end
    else begin
        cnt_20us <= cnt_20us + 1'd1;
    end
end



// 单个信号sel_r位 片选 拼接约束，实现动态扫描
always @(posedge Clk or negedge Rst_n) begin
    if (!Rst_n) begin
        sel_r <= 8'b11_11_11_10;
    end
    else if (cnt_20us == MAX20us - 1'd1) begin
        sel_r <= {sel_r[6:0],sel_r[7]};//向左循环移动
    end
    else begin
        sel_r <= sel_r;
    end
end



// 根据选择信号sel_r获取要显示的数字
always @(*) begin
    case (sel_r)//片选信号
        8'b11_11_11_10:     number  = NOTION                                        ;//1
        8'b11_11_11_01:     number  = data_o/10_0000                                ;//2
        8'b11_11_10_11:     number  = (data_o%10_0000)/1_0000                       ;//3
        8'b11_11_01_11:     number  = ((data_o%10_0000)%1_0000)/1000                ;//4
        8'b11_10_11_11:     number  = FUSHU                                         ;//5
        8'b11_01_11_11:     number  = (((data_o%10_0000)%1_0000)%1000)/100          ;//6
        8'b10_11_11_11:     number  = ((((data_o%10_0000)%1_0000)%1000)%100)/10     ;//7
        8'b01_11_11_11:     number  = ((((data_o%10_0000)%1_0000)%1000)%100)%10     ;//8
        default:            number  = 4'd0                                          ;
    endcase
end


/*
// 根据选择信号sel_r获取要显示的数字
always @(*) begin
    case (sel_r)//片选信号
        8'b11_11_11_10:     number  = NOTION                                        ;//1
        8'b11_11_11_01:     number  = data_o/10_000                              ;//2
        8'b11_11_10_11:     number  = (data_o%10_000)/1_000                       ;//3
        8'b11_11_01_11:     number  = ((data_o%10_000)%1_000)/1000                ;//4
        8'b11_10_11_11:     number  = FUSHU                                         ;//5
        8'b11_01_11_11:     number  = (((data_o%10_000)%1_000)%1000)/100          ;//6
        8'b10_11_11_11:     number  = ((((data_o%10_000)%1_000)%1000)%100)/10     ;//7
        8'b01_11_11_11:     number  = ((((data_o%10_000)%1_000)%1000)%100)%10     ;//8
        default:            number  = 4'd0                                          ;
    endcase
end

*/



// 根据数字解析出对应的七段显示器段选值seg_r, 低电平点亮，高电平熄灭
always @(*) begin
    case (number)                   //654_3210     
        4'd0    :       seg_r   =  7'b100_0000;//_    7 段数码管的点在 DE2-115 开发板上是不可用的
        4'd1    :       seg_r   =  7'b111_1001;//1
        4'd2    :       seg_r   =  7'b010_0100;//2
        4'd3    :       seg_r   =  7'b011_0000;//3
        4'd4    :       seg_r   =  7'b001_1001;//4
        4'd5    :       seg_r   =  7'b001_0010;//5
        4'd6    :       seg_r   =  7'b000_0010;//6
        4'd7    :       seg_r   =  7'b111_1000;//7
        4'd8    :       seg_r   =  7'b000_0000;//8
        4'd9    :       seg_r   =  7'b001_0000;//9
        NOTION  :       seg_r   =  7'b111_1111;// 灭 定义消隐的编码
        FUSHU   :       seg_r   =  7'b111_0111;// 定义小数点的编码
        default :       seg_r   =  7'b111_1111;// 默认消隐
    endcase
end


//根据片选信号sel_r
// 根据选择信号sel_r将seg_r值赋给对应的七段显示器寄存器
always @(*) begin
    case (sel_r)//sel_r片选信号
		8'b11_11_11_10:     hex1_r = seg_r;//seg_r段选信号
		8'b11_11_11_01:     hex2_r = seg_r;
		8'b11_11_10_11:     hex3_r = seg_r;
		8'b11_11_01_11:     hex4_r = seg_r;
		8'b11_10_11_11:     hex5_r = seg_r;
		8'b11_01_11_11:     hex6_r = seg_r;
		8'b10_11_11_11:     hex7_r = seg_r;
		8'b01_11_11_11:     hex8_r = seg_r;
		default:            seg_r  = seg_r;
	endcase
end

// 将寄存器的值赋予输出端口
assign  hex1 = hex1_r;
assign  hex2 = hex2_r;
assign  hex3 = hex3_r;
assign  hex4 = hex4_r;
assign  hex5 = hex5_r;
assign  hex6 = hex6_r;
assign  hex7 = hex7_r;
assign  hex8 = hex8_r;

endmodule